﻿#include <ctype.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include "hello_h.h"
#pragma comment(lib, "Rpcrt4.lib")

int server_ReceiveMsgCb(const wchar_t *msg)
{
    wprintf(L"客户端收到消息: %s\n", msg);
    return 0;
}

BOOL WINAPI ctrlCHandler(DWORD /*signal*/)
{
    unsigned long ulCode = 0;
    RpcTryExcept
    {
        client_Shutdown();
    }
    RpcExcept(1)
    {
        ulCode = RpcExceptionCode();
        printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
    }
    RpcEndExcept

    exit(0);
}

int main()
{
    RPC_STATUS status;
    RPC_WSTR pszStringBinding = NULL;
    unsigned long ulCode = 0;

    setlocale(LC_ALL, "chs"); // 这是个大坑，不设置中文直接不见了。。。
    SetConsoleCtrlHandler(ctrlCHandler, TRUE); // 注册 Ctrl+C 处理函数
    // Creates a string binding handle.
    // This function is nothing more than a printf.
    // Connection is not done here.
    status = RpcStringBindingCompose(NULL,                                             // UUID to bind to
                                     reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"ncalrpc"), // Use TCP/IP protocol
                                     NULL,                                             // TCP/IP network address to use
                                     reinterpret_cast<RPC_WSTR>((RPC_WSTR)L"tmp_endpoint"), // TCP/IP port to use
                                     NULL,             // Protocol dependent network options to use
                                     &pszStringBinding // String binding output
    );

    if (status)
        exit(status);

    // Validates the format of the string binding handle and converts
    // it to a binding handle.
    // Connection is not done here either.
    status =
        RpcBindingFromStringBinding(pszStringBinding, // The string binding to validate
                                    &hHelloBinding);  // Put the result in the implicit binding(defined in the IDL file)

    if (status)
        exit(status);

    RpcTryExcept
    {
        // 建立RPC通道，让服务端能够调用客户端的回调函数。（该接口会被服务端阻塞直到异常退出）
        client_EnableReceiveMsg();

        // 意义不大。如果上面不被阻塞，说明是异常退出，应该直接就到异常那里去了
        client_Shutdown();
    }
    RpcExcept(1)
    {
        ulCode = RpcExceptionCode();
        printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode);
    }
    RpcEndExcept

    // Free the memory allocated by a string
    status = RpcStringFree(&pszStringBinding);
    if (status)
        exit(status);

    // Releases binding handle resources and disconnects from the server
    status = RpcBindingFree(&hHelloBinding);
    if (status)
        exit(status);

    exit(0);
}
